#include "Communication.h"

Communication* Communication::m_communicationInstances[] = { 0 };

/* Constructor */
Communication::Communication(Stream* serialPort, CommunicationListener* communucationListener)
{
  m_nbOfByte = 0;
  m_serialPort = serialPort;
  m_communucationListener = communucationListener;
}

Communication* Communication::add(Stream* serialPort, CommunicationListener* communucationListener)
{
  int index = 0;
  Communication* communicationInstance;
  for(; index<NB_OF_SERIAL_COMMUNICATION; index++)
  {
    if (Communication::m_communicationInstances[index] == 0)
	{
	  Communication::m_communicationInstances[index] = new Communication::Communication(serialPort, communucationListener);
	  break;
	}
	else
	{
	  /* communication already exists in this position */
	}
  }
  if (index == NB_OF_SERIAL_COMMUNICATION)
  {
    communicationInstance = NULL;
  }
  else
  {
    communicationInstance = Communication::m_communicationInstances[index];
  }
  return communicationInstance;
}

/* METHODES */

void Communication::byteReceived(Stream* serialPort, byte byteReceived)
{
  for(int i=0; i<3; i++)
  {
    if (serialPort == Communication::m_communicationInstances[i]->getStream())
	{
	  Communication::m_communicationInstances[i]->byteReceived(byteReceived);
	}
	else
	{
	  /* no communication found */
	}
  }
}

/**
* \brief Send a command over Serial port
* \param command
* \return none
*/
Stream* Communication::getStream()
{
  return m_serialPort;
}

/**
* \brief Send a command over Serial port
* \param command
* \return none
*/
void Communication::sendCommand(Command* command)
{
  byte dataToTransmit[COMMAND_SIZE];
  byte caclulatedCRC;
  command->serialize(dataToTransmit);
  CRC* crc = new CRC();
  for(int i=0; i<COMMAND_SIZE; i++)
  {
    caclulatedCRC = crc->update(dataToTransmit[i]);
    m_serialPort->write(dataToTransmit[i]);
  }
  m_serialPort->write(caclulatedCRC);
  delete crc;
}

/**
* \brief Fill a command with the new byte received, or check CRC and give the command to its listener
* \param byte
* \return none
*/
void Communication::byteReceived(byte receivedByte)
{
  byte crc = 0xFF;
  switch (m_nbOfByte)
  {
    case 0:
      m_CRCInReception = new CRC();
      m_commandInReception = new Command();
      
    case 1:
    case 2:
      m_commandInReception->addByte(receivedByte);
      m_CRCInReception->update(receivedByte);
      m_nbOfByte++;
      break;
    
    case 3:
      crc = m_CRCInReception->update(receivedByte);
      if (crc == 0)
      {
        m_communucationListener->commandReceived(m_commandInReception);
      }
      else
      {
        /* Reception NOT ok */
		m_communucationListener->commandReceived(m_commandInReception);
      }
      delete m_CRCInReception;
      m_CRCInReception = NULL;
      m_nbOfByte = 0;
      break;
    
    default:
      break;
  }
}
